import 'dart:convert';

import 'package:common_utils/common_utils.dart';
import 'package:dio/dio.dart';
import 'package:paly_android/net/http_result.dart';
import 'package:paly_android/util/toast_util.dart';

import 'error_handle.dart';

/// 默认dio配置
int _connectTimeout = 15000;
int _receiveTimeout = 15000;
int _sendTimeout = 10000;
String _baseUrl = '';
List<Interceptor> _interceptors = [];

/**
 * 网络成功回调
 */
typedef OnNetSuccess<T> = Function(T data);
/**
 * 网络错误回调
 */
typedef OnNetError = Function(int code, String msg);

/// 初始化Dio配置
void configDio({
  int? connectTimeout,
  int? receiveTimeout,
  int? sendTimeout,
  String? baseUrl,
  List<Interceptor>? interceptors,
}) {
  _connectTimeout = connectTimeout ?? _connectTimeout;
  _receiveTimeout = receiveTimeout ?? _receiveTimeout;
  _sendTimeout = sendTimeout ?? _sendTimeout;
  _baseUrl = baseUrl ?? _baseUrl;
  _interceptors = interceptors ?? _interceptors;
}

class DioClient {
  DioClient._() {
    final BaseOptions _options = BaseOptions(
      connectTimeout: _connectTimeout,
      receiveTimeout: _receiveTimeout,
      sendTimeout: _sendTimeout,

      /// dio默认json解析，这里指定返回UTF8字符串，自己处理解析。（可也以自定义Transformer实现）
      responseType: ResponseType.plain,
      validateStatus: (_) {
        // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
        return true;
      },
      baseUrl: _baseUrl,
//      contentType: Headers.formUrlEncodedContentType, // 适用于post form表单提交
    );

    _dio = Dio(_options);

    /// Fiddler抓包代理配置 https://www.jianshu.com/p/d831b1f7c45b
//    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
//        (HttpClient client) {
//      client.findProxy = (uri) {
//        //proxy all request to localhost:8888
//        return 'PROXY 10.41.0.132:8888';
//      };
//      client.badCertificateCallback =
//          (X509Certificate cert, String host, int port) => true;
//    };

    /// 添加拦截器
    void addInterceptor(Interceptor interceptor) {
      _dio.interceptors.add(interceptor);
    }

    _interceptors.forEach(addInterceptor);
  }

  factory DioClient() => _client;

  static final DioClient _client = DioClient._();

  static DioClient get instance => DioClient();

  static late Dio _dio;

  Dio get dio => _dio;

  Options _checkOptions(String method, Options? options) {
    options ??= Options();
    options.method = method;
    return options;
  }

  /**
   * 所有的网络请求都走此方法
   */
  Future<HttpResult<T>> _request<T>(
    Method method,
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    CancelToken? cancelToken,
  }) async {
    //发起网络请求
    // SmartDialog.showLoading(msg: "正在加载");
    Response<String> response = await _dio.request<String>(path,
        queryParameters: queryParameters,
        options: _checkOptions(method.value, options),
        cancelToken: cancelToken);
    // TimerStream(1,Duration(seconds: 3)).listen((event) {
    //   SmartDialog.dismiss(closeType: 3);
    // });

    //数据脱壳
    try {
      String data = response.data.toString();
      final Map<String, dynamic> _map = json.decode(data);
      return HttpResult.formJson(_map);
    } catch (e) {
      LogUtil.e(e.toString());
      return HttpResult<T>(ExceptionHandle.parse_error, '数据解析错误！', null);
    }
  }

  void _onError(int? code, String msg, OnNetError? onError) {
    if (code == null) {
      code = ExceptionHandle.unknown_error;
      msg = '未知异常';
    }

    onError?.call(code, msg);
  }

  /**
   * 网络成功结果解析
   */
  dynamic _parseNetSuccessResult<T>(HttpResult<T> bean,
      OnNetSuccess<T>? onNetSuccess, OnNetError? onNetError) {
    if (bean.isOk()) {
      dynamic data=bean.data as T;
      onNetSuccess?.call(data);
      return data;
    } else {
      showLongToast(bean.msg);
      _onError(bean.code, bean.msg, onNetError);
    throw Exception(bean.msg);
    }
  }

  /**
   * 网络失败结果解析
   */
  void _parseNetErrorResult(dynamic e, OnNetError? onNetError) {
    final NetError error = ExceptionHandle.handleException(e);
    showLongToast(error.toString());
    _onError(error.code, error.msg, onNetError);
  }

  /**
   * 封装get请求
   */
  Future<T> get<T>(
    String path, {
    OnNetSuccess<T>? onSuccess,
    OnNetError? onError,
    Map<String, dynamic>? parameters,
    CancelToken? cancelToken,
    Options? options,
  }) async {
    return  await _request<T>(Method.get, path,
            queryParameters: parameters,
            cancelToken: cancelToken,
            options: options)
        .then<T>((HttpResult<T> bean) {
      dynamic data=_parseNetSuccessResult<T>(bean, onSuccess, onError);
      return Future.value(data);
    }, onError: (dynamic e) {
      _parseNetErrorResult(e, onError);
      return Future.error(ExceptionHandle.handleException(e));
    });
  }

  /**
   * 封装post请求
   */
  Future<T> post<T>(
    String path, {
    OnNetSuccess<T>? onSuccess,
    OnNetError? onError,
    Map<String, dynamic>? parameters,
    CancelToken? cancelToken,
    Options? options,
  }) async {
    return await _request<T>(Method.post, path,
         queryParameters: parameters, cancelToken: cancelToken, options: options)
        .then<T>((HttpResult<T> bean) {
      dynamic data=_parseNetSuccessResult<T>(bean, onSuccess, onError);
      return data;
    }, onError: (dynamic e) {
      _parseNetErrorResult(e, onError);
      return ExceptionHandle.handleException(e);
    });
  }
}

enum Method { get, post, put, patch, delete, head }

/// 使用拓展枚举替代 switch判断取值
/// https://zhuanlan.zhihu.com/p/98545689
extension MethodExtension on Method {
  String get value => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD'][index];
}
